﻿#region Imports
using System;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;

using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
#endregion

namespace SqlMetalBuilder
{
    public partial class MDIChildProject : Form
    {
        private string ProjectFileName;
        private string ProjectFilePath;
        public MDIChildProject()
        {
            InitializeComponent();
        }


        private void MDIChildProject_Load(object sender, EventArgs e)
        {
            cboCodeLanguage.SelectedIndex = 0;
            cboSerialization.SelectedIndex = 0;
            cboAuthentication.SelectedIndex = 0;

            cboDatabase.Items.Add("");
            cboDatabase.SelectedIndex = 0;
            txtServerName.Focus();
        }

        private void rdoConnectionString_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoConnectionString.Checked)
                DataSourceChanged();
        }

        private void rdoInputFile_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoInputFile.Checked)
                DataSourceChanged();
        }

        private void rdoDatabase_CheckedChanged(object sender, EventArgs e)
        {
            if (rdoDatabase.Checked)
                DataSourceChanged();
        }
        private void DataSourceChanged()
        {
            if (rdoDatabase.Checked)
            {
                chkDefaultServer.Enabled = true;
                cboAuthentication.Enabled = true;
                txtServerName.Enabled = !chkDefaultServer.Checked;
                txtUserName.Enabled = cboAuthentication.SelectedIndex == 1;
                txtPassword.Enabled = cboAuthentication.SelectedIndex == 1;
                cboDatabase.Enabled = true;
                btnTestConnection.Enabled = true;
                txtConnectionString.Enabled = false;
                txtInputFile.Enabled = false;
                btnBrowserInputFile.Enabled = false;
            }
            else if (rdoConnectionString.Checked)
            {
                txtServerName.Enabled = false;
                chkDefaultServer.Enabled = false;
                cboAuthentication.Enabled = false;
                txtUserName.Enabled = false;
                txtPassword.Enabled = false;
                cboDatabase.Enabled = false;
                btnTestConnection.Enabled = false;
                txtConnectionString.Enabled = true;
                txtInputFile.Enabled = false;
                btnBrowserInputFile.Enabled = false;
            }
            else if (rdoInputFile.Checked)
            {
                txtServerName.Enabled = false;
                txtUserName.Enabled = false;
                chkDefaultServer.Enabled = false;
                cboAuthentication.Enabled = false;
                txtPassword.Enabled = false;
                cboDatabase.Enabled = false;
                btnTestConnection.Enabled = false;
                txtConnectionString.Enabled = false;
                txtInputFile.Enabled = true;
                btnBrowserInputFile.Enabled = true;
            }
        }


        private void btnTestConnection_Click(object sender, EventArgs e)
        {
            SqlConnectionStringBuilder objSqlConnectionStringBuilder = new SqlConnectionStringBuilder();
            if (!chkDefaultServer.Checked && txtServerName.Text.Trim().Length == 0)
            {
                MessageBox.Show("Please enter server name");
                txtServerName.Focus();
                return;
            }
            if (cboAuthentication.SelectedIndex == 1)
            {
                if (txtUserName.Text.Trim().Length == 0)
                {
                    MessageBox.Show("Please enter user name");
                    txtUserName.Focus();
                    return;
                }
                if (txtPassword.Text.Trim().Length == 0)
                {
                    MessageBox.Show("Please enter password");
                    txtPassword.Focus();
                    return;
                }
            }
            if (chkDefaultServer.Checked)
                objSqlConnectionStringBuilder.DataSource = "localhost/sqlexpress";
            else
                objSqlConnectionStringBuilder.DataSource = txtServerName.Text.Trim();

            if (cboAuthentication.SelectedIndex == 0)
            {
                objSqlConnectionStringBuilder.IntegratedSecurity = true;
            }
            else
            {
                objSqlConnectionStringBuilder.UserID = txtUserName.Text;
                objSqlConnectionStringBuilder.Password = txtPassword.Text;
            }
                cboDatabase.Items.Clear();
                cboDatabase.Items.Add("");
            try
            {
                SqlConnection objSqlConnection = new SqlConnection(objSqlConnectionStringBuilder.ConnectionString);
                this.Cursor = Cursors.WaitCursor;
                btnTestConnection.Enabled = false;
                objSqlConnection.Open();
                DataTable objDataTable = objSqlConnection.GetSchema("databases");
                foreach (DataRow objDataRow in objDataTable.Rows)
                    cboDatabase.Items.Add(objDataRow[0]);

                objSqlConnection.Close();
                this.Cursor = Cursors.Default;
                MessageBox.Show("Connection Successful");
            }
            catch (SqlException objSqlException)
            {
                MessageBox.Show("Connection can not be established");
            }
            finally
            {
                this.Cursor = Cursors.Default;
                btnTestConnection.Enabled = true;
            }
        }

        private void btnBrowserInputFile_Click(object sender, EventArgs e)
        {

            objFileDialog.Filter = "SQL Server Express .mdf file(*.mdf)|*.mdf|SQL Server Compact 3.5 .sdf file(*.sdf)|*.sdf|Dbml intermediate file(*.dbml)|*.dbml";
            if (objFileDialog.ShowDialog(this) == DialogResult.OK)
                txtInputFile.Text = objFileDialog.FileName;
        }

        private void btnBrowserDBML_Click(object sender, EventArgs e)
        {
            objSaveFileDialog.DefaultExt = "dbml";
            objSaveFileDialog.Filter = "Dbml intermediate file (*.dbml)|*.dbml";
            if (objSaveFileDialog.ShowDialog(this) == DialogResult.OK)
                txtDBML.Text = objSaveFileDialog.FileName;
        }

        private void btnBrowserCode_Click(object sender, EventArgs e)
        {
            objSaveFileDialog.DefaultExt = "cs";
            objSaveFileDialog.Filter = "Visual C# (*.cs)|*.cs|VB.NET (*.vb)|*.vb";
            if (objSaveFileDialog.ShowDialog(this) == DialogResult.OK)
                txtCode.Text = objSaveFileDialog.FileName;
        }

        private void btnBrowserMap_Click(object sender, EventArgs e)
        {
            objSaveFileDialog.DefaultExt = "map";
            objSaveFileDialog.Filter = "XML mapping file (*.map)|*.map";
            if (objSaveFileDialog.ShowDialog(this) == DialogResult.OK)
                txtMap.Text = objSaveFileDialog.FileName;
        }
        public void Build()
        {
            try
            {
                SqlMetal objSqlMetal = new SqlMetal();
                string strErrorMessage = string.Empty;
                Control objErrorControl = null;
                if (FillSqlMetalParameters(objSqlMetal, ref strErrorMessage, ref objErrorControl) != 0)
                {
                    MessageBox.Show(strErrorMessage);
                    objErrorControl.Focus();
                    return;
                }
                this.Cursor = Cursors.WaitCursor;
                txtOutput.Text = "";
                Application.DoEvents();
                string strSqlMetalExeLocation = SqlMetal.GetExeLocation();
                Process objBackGroundProcess = new Process();
                objBackGroundProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                objBackGroundProcess.StartInfo.CreateNoWindow = true;
                objBackGroundProcess.StartInfo.RedirectStandardOutput = true;
                objBackGroundProcess.StartInfo.RedirectStandardInput = false;
                objBackGroundProcess.StartInfo.UseShellExecute = false;
                objBackGroundProcess.StartInfo.FileName = strSqlMetalExeLocation;
                objBackGroundProcess.StartInfo.Arguments = objSqlMetal.GetArguments();
                objBackGroundProcess.Start();
                this.txtOutput.Text = objBackGroundProcess.StandardOutput.ReadToEnd();
                this.txtOutput.ScrollToCaret();
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        public void ExportToBatchFile()
        {
            SqlMetal objSqlMetal = new SqlMetal();
            string strErrorMessage = string.Empty;
            Control objErrorControl = null;
            if (FillSqlMetalParameters(objSqlMetal, ref strErrorMessage, ref objErrorControl) != 0)
            {
                MessageBox.Show(strErrorMessage);
                objErrorControl.Focus();
                return;
            }
            string strSqlMetalExeLocation = SqlMetal.GetExeLocation();
            string strSqlMetalArguments = objSqlMetal.GetArguments();
            objSaveFileDialog.DefaultExt = "BAT";
            objSaveFileDialog.Filter = "Batch File(*.bat)|*.bat";
            if (objSaveFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                File.WriteAllText(objSaveFileDialog.FileName, "\"" + strSqlMetalExeLocation + "\"" + strSqlMetalArguments); ;
            }
        }
        private int FillSqlMetalParameters(SqlMetal objSqlMetal, ref string errorMesage, ref Control errorControl)
        {
            objSqlMetal.ServerName = txtServerName.Text.Trim();
            objSqlMetal.IsServerNameDefault = chkDefaultServer.Checked;
            objSqlMetal.UserName = txtUserName.Text.Trim();
            objSqlMetal.Password = txtPassword.Text.Trim();
            objSqlMetal.Database = (string)cboDatabase.SelectedItem;
            objSqlMetal.ConnectionString = txtConnectionString.Text.Trim();
            objSqlMetal.InputFile = txtInputFile.Text.Trim();
            objSqlMetal.TimeOut = (int)numTimeOut.Value;
            objSqlMetal.IsDefaultTimeOut = chkTimeOutDefault.Checked;
            if (rdoDatabase.Checked)
            {
                objSqlMetal.ConnectionOption = SqlMetalConnectionOptions.Database;
                if (cboAuthentication.SelectedIndex == 0)
                {
                    objSqlMetal.AuthenticationType = AuthenticationType.Windows;
                }
                else
                {
                    objSqlMetal.AuthenticationType = AuthenticationType.SQLServer;
                }
            }
            else if (rdoConnectionString.Checked)
            {
                objSqlMetal.ConnectionOption = SqlMetalConnectionOptions.ConnectionString;
            }
            else if (rdoInputFile.Checked)
            {
                objSqlMetal.ConnectionOption = SqlMetalConnectionOptions.InputFile;
            }

            objSqlMetal.IsDbmlOutputFile = rdoDBML.Checked;


            objSqlMetal.IsDbmlPreview = chkDBMLPreview.Checked;

            objSqlMetal.DbmlOutputFile = txtDBML.Text.Trim();

            objSqlMetal.IsCodeOutputFile = rdoCode.Checked;

            objSqlMetal.IsCodePreview = chkCodePreview.Checked;

            objSqlMetal.CodeOutputFile = txtCode.Text.Trim();
            objSqlMetal.IsMapOutputFile = chkMap.Checked;
            objSqlMetal.MapOutputFile = txtMap.Text.Trim();


            objSqlMetal.NameSpace = txtNamespace.Text.Trim();
            objSqlMetal.DataContext = txtContextClass.Text.Trim();
            objSqlMetal.BaseClass = txtBaseClass.Text.Trim();

            if (cboCodeLanguage.SelectedIndex == 0)
                objSqlMetal.enmLanguage = Language.Default;
            else if (cboCodeLanguage.SelectedIndex == 1)
                objSqlMetal.enmLanguage = Language.CSharp;
            else if (cboCodeLanguage.SelectedIndex == 2)
                objSqlMetal.enmLanguage = Language.VBDotNet;

            if (cboSerialization.SelectedIndex == 0)
                objSqlMetal.enmSerialzation = Serialzation.Default;
            else if (cboSerialization.SelectedIndex == 1)
                objSqlMetal.enmSerialzation = Serialzation.None;
            else if (cboSerialization.SelectedIndex == 2)
                objSqlMetal.enmSerialzation = Serialzation.Unidirectional;
            objSqlMetal.IsPuralize = chkPluralize.Checked;
            objSqlMetal.IncludeDatabaseFunctions = chkDatabaseFunctions.Checked;
            objSqlMetal.IncludeDatabaseStoredProcedure = chkDatabaseStoredProcedures.Checked;
            objSqlMetal.IncludeDatabaseViews = chkDatabaseViews.Checked;
            if (rdoDatabase.Checked)
            {
                if (cboAuthentication.SelectedIndex == 0)
                {
                }
                else
                {
                    if (txtUserName.Text.Trim().Length == 0)
                    {
                        errorMesage = "User name can not be left blank.";
                        errorControl = txtUserName;
                        return -1;
                    }
                    if (txtPassword.Text.Trim().Length == 0)
                    {
                        errorMesage = "Password can not be left blank.";
                        errorControl = txtPassword;
                        return -1;
                    }
                }

                if (cboDatabase.SelectedIndex == 0)
                {
                    errorMesage = "Please select database.";
                    errorControl = cboDatabase;
                    return -1;
                }
            }
            else if (rdoConnectionString.Checked)
            {
                if (txtConnectionString.Text.Trim().Length == 0)
                {
                    errorMesage = "Connection string can not be left blank.";
                    errorControl = txtConnectionString;
                    return -1;
                }
            }
            else if (rdoInputFile.Checked)
            {
                if (txtInputFile.Text.Trim().Length == 0)
                {
                    errorMesage = "Input file can not be left blank.";
                    errorControl = txtInputFile;
                    return -1;
                }
            }
            if (txtNamespace.Text.Trim().Contains(" "))
            {
                errorMesage = "Namespace name can not contain spaces.";
                errorControl = txtNamespace;
                return -1;
            }
            if (txtContextClass.Text.Trim().Contains(" "))
            {
                errorMesage = "Data context class name can not contain spaces.";
                errorControl = txtContextClass;
                return -1;
            }
            if (txtBaseClass.Text.Trim().Contains(" "))
            {
                errorMesage = "Base class name can not contain spaces.";
                errorControl = txtBaseClass;
                return -1;
            }

            return 0;
        }

        private void chkMap_CheckedChanged(object sender, EventArgs e)
        {
            txtMap.Enabled = chkMap.Checked;
            btnBrowserMap.Enabled = chkMap.Checked;
        }

        private void cboAuthentication_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cboAuthentication.SelectedIndex == 0)
            {
                txtUserName.Enabled = txtPassword.Enabled = false;
                txtPassword.Text = "";
            }
            else
            {
                txtUserName.Enabled = txtPassword.Enabled = true;
            }
        }

        private void chkDefaultServer_CheckedChanged(object sender, EventArgs e)
        {
            txtServerName.Enabled = !chkDefaultServer.Checked;
        }

        private void rdoDBML_CheckedChanged(object sender, EventArgs e)
        {
            chkDBMLPreview.Enabled = rdoDBML.Checked;
            txtDBML.Enabled = btnBrowserDBML.Enabled = rdoDBML.Checked && !chkDBMLPreview.Checked;
        }

        private void rdoCode_CheckedChanged(object sender, EventArgs e)
        {
            chkCodePreview.Enabled = rdoCode.Checked;
            chkMap.Enabled = txtCode.Enabled = btnBrowserCode.Enabled = rdoCode.Checked && !chkCodePreview.Checked;
            txtMap.Enabled = btnBrowserMap.Enabled = rdoCode.Checked && chkMap.Checked && !chkCodePreview.Checked;
        }

        private void chkDBMLPreview_CheckedChanged(object sender, EventArgs e)
        {
            txtDBML.Enabled = btnBrowserDBML.Enabled = !chkDBMLPreview.Checked;
        }

        private void chkCodePreview_CheckedChanged(object sender, EventArgs e)
        {
            chkMap.Enabled = txtCode.Enabled = btnBrowserCode.Enabled = rdoCode.Checked && !chkCodePreview.Checked;
            txtMap.Enabled = btnBrowserMap.Enabled = rdoCode.Checked && chkMap.Checked && !chkCodePreview.Checked;

        }

        private void chkTimeOutDefault_CheckedChanged(object sender, EventArgs e)
        {
            numTimeOut.Enabled = !chkTimeOutDefault.Checked;
        }

        public void SaveProject(string filePath)
        {
            SqlMetal objSqlMetal = new SqlMetal();
            string strErrorMessage = string.Empty;
            Control objErrorControl = null;
            FillSqlMetalParameters(objSqlMetal, ref strErrorMessage, ref objErrorControl);
            Stream stream = File.Open(filePath, FileMode.Create);
            BinaryFormatter objBinaryFormatter = new BinaryFormatter();
            objBinaryFormatter.Serialize(stream, objSqlMetal);
            stream.Close();
            this.ProjectFilePath = filePath;
            this.ProjectFileName = Path.GetFileNameWithoutExtension(filePath);
            this.Text = this.ProjectFileName;
        }
        //public void SaveProject()
        //{
            
                
        //    SqlMetal objSqlMetal = new SqlMetal();
        //    string strErrorMessage = string.Empty;
        //    Control objErrorControl = null;
        //    FillSqlMetalParameters(objSqlMetal, ref strErrorMessage, ref objErrorControl);
        //    Stream stream = File.Open(strFilePath, FileMode.Create);
        //    BinaryFormatter objBinaryFormatter = new BinaryFormatter();
        //    objBinaryFormatter.Serialize(stream, objSqlMetal);
        //    stream.Close();
        //}
        public void LoadProject(string filePath)
        {
            SqlMetal objSqlMetal = new SqlMetal();
            Stream stream = File.Open(filePath, FileMode.Open);
            BinaryFormatter bFormatter = new BinaryFormatter();
            objSqlMetal = (SqlMetal)bFormatter.Deserialize(stream);
            stream.Close();


            txtServerName.Text = objSqlMetal.ServerName;
            chkDefaultServer.Checked=objSqlMetal.IsServerNameDefault;
            txtUserName.Text = objSqlMetal.UserName;
            txtPassword.Text = objSqlMetal.Password;
            cboDatabase.Items.Add("");
            cboDatabase.Items.Add(objSqlMetal.Database);
            cboDatabase.SelectedIndex = 1;
            txtConnectionString.Text = objSqlMetal.ConnectionString;
            txtInputFile.Text = objSqlMetal.InputFile;
            numTimeOut.Value = objSqlMetal.TimeOut;
            chkTimeOutDefault.Checked = objSqlMetal.IsDefaultTimeOut;
            if (objSqlMetal.ConnectionOption == SqlMetalConnectionOptions.Database)
            {
                rdoDatabase.Checked = true;

                if (objSqlMetal.AuthenticationType == AuthenticationType.Windows)
                {
                    cboAuthentication.SelectedIndex = 0;
                }
                else
                {
                    cboAuthentication.SelectedIndex = 1;
                }
            }
            else if (objSqlMetal.ConnectionOption == SqlMetalConnectionOptions.ConnectionString)
            {
                rdoConnectionString.Checked = true;
            }
            else if (objSqlMetal.ConnectionOption == SqlMetalConnectionOptions.InputFile)
            {
                rdoInputFile.Checked = true;
            }

            rdoDBML.Checked = objSqlMetal.IsDbmlOutputFile;


            chkDBMLPreview.Checked = objSqlMetal.IsDbmlPreview;

            txtDBML.Text = objSqlMetal.DbmlOutputFile;

            rdoCode.Checked = objSqlMetal.IsCodeOutputFile;

            chkCodePreview.Checked = objSqlMetal.IsCodePreview;

            txtCode.Text = objSqlMetal.CodeOutputFile;
            chkMap.Checked = objSqlMetal.IsMapOutputFile;
            txtMap.Text = objSqlMetal.MapOutputFile;


            txtNamespace.Text = objSqlMetal.NameSpace;
            txtContextClass.Text = objSqlMetal.DataContext;
            txtBaseClass.Text = objSqlMetal.BaseClass;

            if (objSqlMetal.enmLanguage == Language.Default)
                cboCodeLanguage.SelectedIndex = 0;
            else if (objSqlMetal.enmLanguage == Language.CSharp)
                cboCodeLanguage.SelectedIndex = 1;
            else if (objSqlMetal.enmLanguage == Language.VBDotNet)
                cboCodeLanguage.SelectedIndex = 2;

            if (objSqlMetal.enmSerialzation == Serialzation.Default)
                cboSerialization.SelectedIndex = 0;
            else if (objSqlMetal.enmSerialzation == Serialzation.None)
                cboSerialization.SelectedIndex = 1;
            else if (objSqlMetal.enmSerialzation == Serialzation.Unidirectional)
                cboSerialization.SelectedIndex = 2;
            chkPluralize.Checked = objSqlMetal.IsPuralize;

            chkDatabaseFunctions.Checked = objSqlMetal.IncludeDatabaseFunctions;
            chkDatabaseStoredProcedures.Checked = objSqlMetal.IncludeDatabaseStoredProcedure;
            chkDatabaseViews.Checked = objSqlMetal.IncludeDatabaseViews;

            this.ProjectFilePath = filePath;
            this.ProjectFileName = Path.GetFileNameWithoutExtension(filePath);
            this.Text = this.ProjectFileName;
        }

        private void buildProjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string strSqlMetalLocation = SqlMetal.GetExeLocation();
            if (!File.Exists(strSqlMetalLocation))
            {
                MessageBox.Show("SqlMetal.exe not found. Please go to Options menu and change SqlMetal.exe location.");
                return;
            }

            MDIParent objMDIParent = (MDIParent)this.MdiParent;
            objMDIParent.StatusText = "Building...";
            Application.DoEvents();
            this.Build();
            objMDIParent.StatusText = "Build complete";
        }

        private void batchFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MDIParent objMDIParent = (MDIParent)this.MdiParent;
            objMDIParent.StatusText = "Exporting...";
            Application.DoEvents();
            this.ExportToBatchFile();
            objMDIParent.StatusText = "Export complete";

        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string strFilePath;
            if (this.ProjectFileName == null)
            {
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                saveFileDialog.Filter = "SqlMetal Builder Project (*.smb)|*.smb";
                if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
                {
                    strFilePath = saveFileDialog.FileName;
                }
                else
                {
                    return;
                }

            }
            else
                strFilePath = this.ProjectFilePath;

            this.SaveProject(strFilePath);
        }  
        private void saveProjectAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            saveFileDialog.Filter = "SqlMetal Builder Project (*.smb)|*.smb";
            if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                string strFileName = saveFileDialog.FileName;
                this.SaveProject(strFileName);
            }
        }

        private void closeProjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        public ToolStrip ToolStrip
        {
            get { return toolStrip1; }
        }
    }
}